<?php

namespace App\Http\Controllers\Admin;

use App\Http\Controllers\Controller;
use App\Models\AfterSaleOrder;
use App\Models\Attribute;
use App\Models\Commodity;
use App\Models\Order;
use App\Models\OrderSku;
use App\Models\Supplier;
use App\Models\Value;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Http\Request;
use Illuminate\Support\Arr;
use Illuminate\Support\Carbon;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\DB;

class CommodityController extends Controller
{
    public function store(Request $request)
    {
        $this->validateCommodityReq($request);

        try {
            DB::beginTransaction();

            $supplier = Supplier::query()->findOrFail($request->supplier_id);
            // 商品
            $commodity = Commodity::query()->create($request->only([
                'name', 'category_id', 'offer_price', 'supplier_id'
            ]));
            $commodity->update(['numbering' => $supplier['numbering'] . str_pad($commodity['id'], 5, 0, STR_PAD_LEFT)]); // 自动填充编号
            // 商品组图
            $commodity->attachments()->sync($request->get('attachment_ids'));

            // 商品规格
            // key
            $specification = array_filter($request->get('specification', []));
            $commodityAttributes = $commodity->attributes()->createMany(array_map(function ($name) {
                return ['name' => $name];
            }, $specification));
            $specificationValue = $request->get('specification_value', []); // sku 详细数据
            // value
            $specificationDetail = $request->get('specification_detail', []);
            $keyWithValue = [];
            foreach ($specification as $key => $name) {
                $keyWithValue[$name] = $specificationDetail[$key] ?? [];
            }
            foreach ($commodityAttributes as $attribute) {
                // key 对应 value
                if (is_array($keyWithValue[$attribute['name']][0])) {
                    // 兼容 sku 第一规格是数组(传递图片)的情况
                    $attributeValues = new Collection();
                    foreach ($keyWithValue[$attribute['name']] as $item) {
                        $attributeValuesTemp = $attribute->values()->create(['content' => $item['value']]);
                        isset($item['sku_picture']) && $attributeValuesTemp->attachments()->sync($item['sku_picture']);
                        $attributeValues->add($attributeValuesTemp);
                    }
                } else {
                    $attributeValues = $attribute->values()->createMany(
                        array_map(
                            function ($value) {
                                return ['content' => $value];
                            },
                            $keyWithValue[$attribute['name']]
                        )
                    );
                }

                // sku 对应的 value_id
                foreach ($specification as $key => $name) { // eg: [8 => '颜色', 9 => '尺码']
                    foreach ($specificationValue as &$specificationValueItem) { // eg: [ [ 8 => '红色', 9 => '大', (其他字段) ... ], ... ];
                        if ($name === $attribute['name']) {
                            $attributeValues->each(function ($item) use (&$specificationValueItem, $key) {
                                if ($item['content'] === $specificationValueItem[$key]) {
                                    $specificationValueItem['value_ids'][] = $item->getKey();
                                }
                            });
                        }
                    }
                }
            }
            // SKU
            foreach ($specificationValue as $valueItem) {
                $sku = $commodity->skus()->create(Arr::only($valueItem, ['entry_price', 'purchase_price']));
                $sku->values()->sync($valueItem['value_ids']);
                // SKU 图片
                if (isset($valueItem['sku_picture'])) {
                    $sku->attachments()->sync([$valueItem['sku_picture']]);
                }
            }

            DB::commit();
        } catch (\Exception $e) {
            DB::rollBack();
            $this->response->errorBadRequest($e->getMessage());
        }

        return $this->response->created(null, $commodity);
    }

    public function list(Request $request)
    {
        return $this->response->array(
            Commodity::query()
                ->with([
                    'attachments',
                    'category:id,name',
                    'supplier:id,name',
                    'attributes.values',
                    'skus.values',
                ])
                ->withCount([
                    'orders' => fn ($query) => $query->where('status', Order::STATUS_SHIPPED),
                    'afterSaleOrders' => fn ($query) => $query->where('status', AfterSaleOrder::STATUS_PASSED)
                ])
                ->when($request->get('name'), function (Builder $builder, $name) {
                    $builder->where('name', 'like', "%$name%");
                })
                ->when($request->get('numbering'), function (Builder $builder, $numbering) {
                    $builder->where('numbering', 'like', "%$numbering%");
                })
                ->when($request->get('supplier_id'), function (Builder $builder, $supplierId) {
                    $builder->where('supplier_id', $supplierId);
                })
                ->when($request->get('category'), function (Builder $builder, $categoryId) {
                    $builder->where('category_id', $categoryId);
                })
                ->when($request->get('updated_at_begin'), function (Builder $builder, $updatedAtBegin) {
                    $builder->where('updated_at', '>=', $updatedAtBegin);
                })
                ->when($request->get('updated_at_end'), function (Builder $builder, $updatedAtEnd) {
                    $builder->where('updated_at', '<=', Carbon::parse($updatedAtEnd)->endOfDay());
                })
                // 把提交的 ID 排在第一个
                ->when($request->get('order_by_id'), function (Builder $builder, $orderById) {
                    $builder->orderByRaw(sprintf('(case when id in (%s) then 1 else 2 end)', implode(',', (array) $orderById)));
                })
                ->withCount(['commodityActivities'])
                ->paginate()
        );
    }

    public function delete($id)
    {
        Commodity::query()->findOrFail($id)->delete();

        return $this->response->noContent();
    }

    public function info($id)
    {
        return $this->response->array(
            Commodity::query()
                ->with([
                    'attachments',
                    'category:id,name',
                    'supplier:id,name',
                    'attributes' => fn($builder) => $builder->with(['values.attachments']),
                    'skus' => fn($builder) => $builder->with(['values', 'attachments']),
                ])
                ->findOrFail($id)
                ->toArray()
        );
    }

    public function update($id, Request $request)
    {
        $this->validateCommodityReq($request);

        try {
            DB::beginTransaction();

            // 商品
            $commodity = Commodity::query()->with(['attributes.values', 'skus.values'])->findOrFail($id);
            $commodity->update($request->only([
                'name', 'category_id', 'offer_price', 'supplier_id', 'supply'
            ]));
            // 商品组图
            $commodity->attachments()->sync($request->get('attachment_ids'));

            // 直接删除 sku 相关, 重建
            foreach ($commodity->attributes as $attribute) {
                $attribute->values()->delete(); // 删除 attributes 对应的值
            }
            Attribute::destroy($commodity->attributes->pluck('id')); // 删除 attributes
            $commodity->attributes()->detach(); // 删除 商品 attributes 关联
            foreach ($commodity->skus as $sku) {
                $sku->values()->detach(); // 删除 sku value 关联
            }
            $commodity->skus()->delete(); // 删除 商品 sku 关联

            // 商品规格
            // key
            $specification = array_filter($request->get('specification', []));
            $commodityAttributes = $commodity->attributes()->createMany(array_map(function ($name) {
                return ['name' => $name];
            }, $specification));
            $specificationValue = $request->get('specification_value', []); // sku 详细数据
            // value
            $specificationDetail = $request->get('specification_detail', []);
            $keyWithValue = [];
            foreach ($specification as $key => $name) {
                $keyWithValue[$name] = $specificationDetail[$key] ?? [];
            }
            foreach ($commodityAttributes as $attribute) {
                // key 对应 value
                if (is_array($keyWithValue[$attribute['name']][0])) {
                    $attributeValues = new Collection();
                    // 兼容 sku 第一规格是数组(传递图片)的情况
                    foreach ($keyWithValue[$attribute['name']] as $item) {
                        $attributeValuesTemp = $attribute->values()->create(['content' => $item['value']]);
                        isset($item['sku_picture']) && $attributeValuesTemp->attachments()->sync($item['sku_picture']);
                        $attributeValues->add($attributeValuesTemp);
                    }
                } else {
                    $attributeValues = $attribute->values()->createMany(
                        array_map(
                            function ($value) {
                                return ['content' => $value];
                            },
                            $keyWithValue[$attribute['name']]
                        )
                    );
                }

                // sku 对应的 value_id
                foreach ($specification as $key => $name) { // eg: [8 => '颜色', 9 => '尺码']
                    foreach ($specificationValue as &$specificationValueItem) { // eg: [ [ 8 => '红色', 9 => '大', (其他字段) ... ], ... ];
                        if ($name === $attribute['name']) {
                            $attributeValues->each(function ($item) use (&$specificationValueItem, $key) {
                                if ($item['content'] === $specificationValueItem[$key]) {
                                    $specificationValueItem['value_ids'][] = $item->getKey();
                                }
                            });
                        }
                    }
                }
            }
            // SKU
            foreach ($specificationValue as $valueItem) {
                $sku = $commodity->skus()->create(Arr::only($valueItem, ['entry_price', 'purchase_price']));
                $sku->values()->sync($valueItem['value_ids']);
                // SKU 图片
                isset($valueItem['sku_picture']) && $sku->attachments()->sync([$valueItem['sku_picture']]);
            }

            DB::commit();
        } catch (\Exception $e) {
            DB::rollBack();
            $this->response->errorBadRequest($e->getMessage());
        }

        return $this->response->noContent();
    }

    private function validateCommodityReq(Request $request)
    {
        validator($request->all(), [
            'specification_value.*.entry_price' => 'required|integer|min:1',
            'specification_value.*.purchase_price' => 'required|integer|min:1',
        ], [
            'specification_value.*.entry_price.required' => '入仓价不得为空',
            'specification_value.*.entry_price.integer' => '入仓价不合法',
            'specification_value.*.entry_price.min' => '入仓价最小一分钱',

            'specification_value.*.purchase_price.required' => '进价不得为空',
            'specification_value.*.purchase_price.integer' => '进价不合法',
            'specification_value.*.purchase_price.min' => '进价最小一分钱',
        ])->validate();
    }
}
